package com.kool.user.service;

import com.alibaba.fastjson.JSON;
import com.kool.leitu.base.cache.KCacheCodeEnum;
import com.kool.leitu.base.cache.KCacheRepo;
import com.kool.leitu.base.exception.AppException;
import com.kool.leitu.base.util.SecurityUtils;
import com.kool.leitu.base.util.StringUtils;
import com.kool.leitu.bean.MenuBean;
import com.kool.leitu.bean.ReqBean;
import com.kool.leitu.service.MenuService;
import com.kool.leitu.service.ReqService;
import com.kool.user.bean.UserAppInfoBean;
import com.kool.user.bean.io.*;
import com.kool.user.bean.vo.UserInfoVo;
import com.kool.user.constant.UserStateEnum;
import com.kool.user.dao.UserAppInfoDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @description:
 * @author: tianhe
 * @create: 2019/02/02 13:45
 */
@Service
@Slf4j
public class UserService {
    @Autowired
    private UserAppInfoDao userAppInfoDao;
    @Autowired
    private MenuService menuService;
    @Autowired
    private ReqService reqService;

    /**
     * 注册
     *
     * @param registerRequest
     */
    public void register(RegisterRequest registerRequest) {

        String pwd = registerRequest.getPwd();
        if (pwd != null && pwd.equals(registerRequest.getPwdC()) == false) {
            throw new AppException(2000002, "密码不一致");
        }

        //查用户是否存在
        UserAppInfoBean userAppInfoBean = userAppInfoDao.selectByLoginName(registerRequest.getLoginName());
        if (userAppInfoBean != null) {
            throw new AppException(2000002, "用户已经存在");
        }
        pwd = SecurityUtils.base64Decode(pwd);
        // 生成随机数N
        int N = 3;
        // 生成加密盐
        String salt = getSalt();
        // 密码密文=sha(密码+|+加密盐,N)
        String encryptPwd = SecurityUtils.sha(pwd + "|" + salt, N);

        userAppInfoBean = new UserAppInfoBean();
        userAppInfoBean.setLoginName(registerRequest.getLoginName());
        userAppInfoBean.setPwd(encryptPwd);
        userAppInfoBean.setHashTimes(N);
        userAppInfoBean.setRegDate(new Date());
        userAppInfoBean.setSaltNew(salt);
        userAppInfoBean.setSaltOld(salt);
        userAppInfoBean.setState(UserStateEnum.ACTIVE.getCode());
        userAppInfoBean.setErrorTimes(0);
        userAppInfoBean.setAvatar("");
        userAppInfoBean.setEmail("");
        userAppInfoBean.setMobile("");
        userAppInfoBean.setNickName("");
        userAppInfoBean.setRegCity("");
        userAppInfoBean.setRegIp("");
        userAppInfoBean.setWechatOpenId("");
        userAppInfoBean.setWechatUnionId("");
        // 写入用户表
        userAppInfoDao.insert(userAppInfoBean);
    }

    /**
     * 预登录
     *
     * @param preLoginRequest
     * @return
     */
    public PreLoginResponse preLogin(PreLoginRequest preLoginRequest) {
        //查用户信息
        UserAppInfoBean userAppInfoBean = userAppInfoDao.selectByLoginName(preLoginRequest.getLoginName());

        PreLoginResponse response = new PreLoginResponse();
        response.setHashTimes(userAppInfoBean.getHashTimes() - 1);
        response.setSaltOld(userAppInfoBean.getSaltOld());
        response.setSaltNew(userAppInfoBean.getSaltNew());

        return response;
    }

    /**
     * 登录
     *
     * @param loginRequest
     * @return
     */
    public LoginResponse login(LoginRequest loginRequest) {
        // 取PwdA/PwdB
        String sPwdATmp = loginRequest.getPwdA();
        String sPwdBTmp = loginRequest.getPwdB();
        // 查询用户信息
        UserAppInfoBean userAppInfoBean = userAppInfoDao.selectByLoginName(loginRequest.getLoginName());
        // 取N
        Integer N = userAppInfoBean.getHashTimes();

        // sha加密1次
        String sPwdA = SecurityUtils.sha(sPwdATmp, 1);
        // 验证密码是否正确

        if (!sPwdA.equals(userAppInfoBean.getPwd())) {
            // 密码错误，更新密码错误次数
            userAppInfoBean.setErrorTimes(userAppInfoBean.getErrorTimes() + 1);
            userAppInfoDao.addErrorTimes(loginRequest.getLoginName());
            throw new AppException(2000003, "密码错误");
        }
        // 更新N/新盐/旧盐/密码/密码错误次数
        if (N == 2) {
            N = getN();
            sPwdBTmp = SecurityUtils.sha(sPwdBTmp, N - 1);
        } else {
            N = N - 1;
        }
        userAppInfoBean.setHashTimes(N);
        userAppInfoBean.setSaltOld(userAppInfoBean.getSaltNew());
        userAppInfoBean.setSaltNew(getSalt());
        userAppInfoBean.setPwd(sPwdBTmp);

        log.debug("密码正确。更新N=" + String.valueOf(N) + ";salt=" + userAppInfoBean.getSaltOld() + ";newSalt="
                + userAppInfoBean.getSaltNew() + ";pwd=" + userAppInfoBean.getPwd());
        userAppInfoDao.updateLogin(userAppInfoBean);

        LoginResponse loginResponse = new LoginResponse();
        loginResponse.setUserId(userAppInfoBean.getId());
        loginResponse.setLoginName(userAppInfoBean.getLoginName());
        loginResponse.setAvatar(userAppInfoBean.getAvatar());
        loginResponse.setNickName(userAppInfoBean.getNickName());
        loginResponse.setToken(SecurityUtils.getToken(userAppInfoBean.getLoginName(), userAppInfoBean.getPwd()));
        return loginResponse;
    }

    private String getSalt() {
        String salt = StringUtils.getUUID().substring(0, 5);
        return salt;
    }

    private int getN() {
        Random random = new Random(System.currentTimeMillis());
        int N = Math.abs(random.nextInt()) % 10000 + 2;
        return N;
    }

    /**
     * 查用户信息
     *
     * @param loginName
     * @return
     */
    public UserInfoVo getUserInfo(String loginName) {
        UserAppInfoBean userAppInfoBean = userAppInfoDao.selectByLoginName(loginName);
        UserInfoVo userInfoVo = JSON.toJavaObject(JSON.parseObject(JSON.toJSONString(userAppInfoBean)), UserInfoVo.class);
        userInfoVo.setToken(SecurityUtils.getToken(loginName, userAppInfoBean.getPwd()));
        return userInfoVo;
    }

    /**
     * 查用户信息
     *
     * @param userId
     * @return
     */
    public UserInfoVo getUserById(Long userId) {
        UserAppInfoBean userAppInfoBean = userAppInfoDao.selectById(userId);
        UserInfoVo userInfoVo = JSON.toJavaObject(JSON.parseObject(JSON.toJSONString(userAppInfoBean)), UserInfoVo.class);
        userInfoVo.setToken(SecurityUtils.getToken(userAppInfoBean.getLoginName(), userAppInfoBean.getPwd()));
        return userInfoVo;

    }

    /**
     * 取用户有权限的菜单
     *
     * @param userId
     * @return
     */
    public List<MenuBean> getMenusOfUser(Long userId) {
        List<MenuBean> menuBeans = KCacheRepo.getInstance().get(KCacheCodeEnum.MENUS_OF_USER_ID.getCode(), String.valueOf(userId));
        if (menuBeans == null || menuBeans.size() <= 0) {
            //用户关联的菜单
            menuBeans = userAppInfoDao.selectMenusOfUser(userId);
            //基础菜单
            List<MenuBean> basicMenu = menuService.getBasicMenu();
            if (basicMenu != null) {
                menuBeans.addAll(basicMenu);
            }
            KCacheRepo.getInstance().put(KCacheCodeEnum.MENUS_OF_USER_ID.getCode(), String.valueOf(userId), menuBeans);
        }
        return mock();
    }

    private List<MenuBean> mock() {
        List<MenuBean> menuBeans = new ArrayList<>();

        menuBeans.add(new MenuBean()
                .setCode("home")
                .setTitle("首页")
                .setRoot("home")
                .setFather("")
                .setDeep(0)
                .setSeq(0)
                .setIndex("/home")
                .setIcon("el-icon-k-home2"));

        menuBeans.add(new MenuBean()
                .setCode("system")
                .setTitle("平台运维")
                .setRoot("system")
                .setFather("")
                .setDeep(0)
                .setSeq(1)
                .setIndex("/sys")
                .setIcon("el-icon-k-setting"));

        menuBeans.add(new MenuBean()
                .setCode("user")
                .setTitle("用户管理")
                .setRoot("system")
                .setFather("system")
                .setDeep(1)
                .setSeq(0)
                .setIndex("/sys-user")
                .setIcon("el-icon-k-user-setting"));

        menuBeans.add(new MenuBean()
                .setCode("genCode")
                .setTitle("代码生成工具")
                .setRoot("system")
                .setFather("system")
                .setDeep(1)
                .setSeq(1)
                .setIndex("/develop-code")
                .setIcon("el-icon-k-user-setting"));

        menuBeans.add(new MenuBean()
                .setCode("genSql")
                .setTitle("sql生成工具")
                .setRoot("system")
                .setFather("system")
                .setDeep(1)
                .setSeq(2)
                .setIndex("/develop-sql")
                .setIcon("el-icon-k-user-setting"));
        return menuBeans;
    }

    /**
     * 取用户有权限的请求
     *
     * @param userId
     * @return
     */
    public List<ReqBean> getReqsOfUser(Long userId) {
        List<ReqBean> reqBeans = KCacheRepo.getInstance().get(KCacheCodeEnum.REQUESTS_OF_USER_ID.getCode(), String.valueOf(userId));
        if (reqBeans == null || reqBeans.size() <= 0) {
            //用户关联的请求
            reqBeans = userAppInfoDao.selectReqsOfUser(userId);
            //基础请求
            reqBeans.addAll(reqService.getBasicReq());
            KCacheRepo.getInstance().put(KCacheCodeEnum.REQUESTS_OF_USER_ID.getCode(), String.valueOf(userId), reqBeans);
        }
        return reqBeans;
    }

}
